import { defineStore } from 'pinia';
import { uid } from 'quasar';
import { cloneDeep } from 'lodash-es';
import { computedGroupLayout } from 'src/pages/BiographicalNotes/common/utils';
import { serializer } from 'src/common/utils';

let count = 0;

export class Group {
  children = [];
  name = 'GroupComponent';
  label = '组' + ++count;
  id;
  layout;
  type = 'group';
  component = () =>
    import('src/pages/BiographicalNotes/components/GroupComponent/GroupComponent.vue');
  parentId;
  index;
  lock = false;
  rotate = false;

  constructor(children, id) {
    this.children = children;
    this.id = id;
    children.forEach((child) => {
      child.parentId = this.id;
    });
    this.layout = computedGroupLayout(children);
  }
}

const components = Object.values(
  import.meta.glob('src/pages/BiographicalNotes/components/Component/**/index.js', {
    eager: true,
  }),
).map((item) => {
  return {
    ...item.default,
    id: uid(),
    model: { ...item.default.model },
    layout: {
      zIndex: 1,
      width: 300,
      height: 300,
      rotate: 0,
      ...item.default.layout,
    },
    lock: false,
    rotate: true,
    component: undefined,
  };
});

export const useNodeTreeStore = defineStore('nodeTree', {
  state: () => {
    const root = {
      children: [],
      id: uid(),
      name: 'root',
      label: '未命名模板',
      layout: {
        padding: 0,
        height: 1123,
        width: 794,
        x: 0,
        y: 0,
      },
      scope: true,
    };

    return {
      componentTree: [
        {
          id: uid(),
          name: 'Components',
          label: '默认组件',
          group: 'node',
          children: components,
        },
      ],
      snapshot: [],
      snapshotIndex: 0,
      treeMap: { [root.id]: root },
      root: root,
      scale: 1,
      tree: [],
      to: null,
      from: null,
      pullMode: 'false',
      activeNode: null,
      activeNodeId: null,
      contextMenu: false,
      activeNodeIds: [],
      moving: false,
      moveMode: 'move',
      temporaryGroup: {
        children: [],
        layout: { x: 0, y: 0, width: 0, height: 0, zIndex: 1, rotate: 0 },
        type: 'temporaryGroup',
        show: false,
        rotate: false,
        id: uid(),
      },
      handelActive: null,
    };
  },

  getters: {
    canRedo() {
      return this.snapshotIndex < this.snapshot.length - 1;
    },
    ids() {
      return new Set(Object.keys(this.treeMap));
    },
    noScope() {
      return !this.root.scope;
    },
  },

  actions: {
    getUID() {
      const maxRetries = 1000;
      let id;
      let retries = 0;

      do {
        id = uid();
        retries++;
        if (retries > maxRetries) {
          throw new Error('Exceeded maximum number of retries for generating a unique ID');
        }
      } while (this.ids.has(id));

      return id;
    },

    recursiveAddTreeMap(newRoot) {
      const recursive = (node) => {
        this.treeMap[node.id] = node;
        if (node.children?.length) {
          node.children.forEach((child) => recursive(child));
        }
      };
      recursive(newRoot);
    },
    setNodeTree(newRoot) {
      this.root = newRoot;
      this.recursiveAddTreeMap(newRoot);
    },
    save() {
      const root = cloneDeep(this.root);
      root.children = serializer.serialize(root.children);

      if (root.dbId != null) {
        root.updateTime = Date.now();
        window.DB.resume.put(root, root.dbId);
      } else {
        root.createTime = Date.now();
        window.DB.resume.add(root).then((dbId) => {
          window.DB.resume.get(dbId).then((dbRoot) => {
            dbRoot.children = serializer.deserialize(dbRoot.children);
            this.root = dbRoot;
            this.recursiveAddTreeMap(this.root);
          });
        });
      }
    },
    clear() {
      this.resizeTemporaryGroup();
      this.setActiveNode(null);
      this.setActiveNode(null);
      this.snapshot = [];
      this.snapshotIndex = 0;
      this.root = {
        children: [],
        id: this.getUID(),
        name: 'root',
        label: '未命名模板',
        layout: {
          padding: 0,
          height: 1123,
          width: 794,
          x: 0,
          y: 0,
        },
        scope: true,
      };
      this.treeMap = {
        [this.root.id]: this.root,
      };
    },
    quit() {
      this.save();
      this.clear();
    },
    /**
     * 复制给定的节点及其所有子节点
     * 此函数通过递归方式创建节点的深拷贝，并更新其id和parentId，同时调整节点的位置
     * 如果节点是临时组类型，则直接复制其所有子节点
     *
     * @param node 待复制的节点
     */
    copyNode(node) {
      /**
       * 递归函数，用于复制节点
       *
       * @param node 当前要复制的节点
       * @param parentId 新节点的父节点id
       * @returns 返回复制后的新节点
       */
      const recursive = (node, parentId) => {
        const newNode = cloneDeep(node);
        newNode.id = this.getUID();
        newNode.parentId = parentId;
        newNode.label = '复制-' + newNode.label;
        this.treeMap[newNode.id] = newNode;
        /**
         * 计算新节点的布局位置
         *
         * @param newNode 新节点
         * @param oldNode 原节点
         */
        const computedNewNodeLayout = (newNode, oldNode) => {
          newNode.layout.x = oldNode.layout.x + 20;
          newNode.layout.y = oldNode.layout.y + 20;
        };
        computedNewNodeLayout(newNode, node);
        if (newNode.children && newNode.children.length > 0) {
          newNode.children = newNode.children.map((child) => {
            return recursive(child, newNode.id);
          });
        }
        return newNode;
      };
      if (node.type === 'temporaryGroup') {
        node.children.forEach((child) => {
          this.copyNode(child);
        });
        return;
      } else {
        const newNode = recursive(node, node.parentId);
        this.treeMap[newNode.parentId].children.push(newNode);
        this.treeMap[newNode.parentId].children.forEach((child, i) => {
          child.index = i;
        });
      }
    },
    createGroup(children) {
      if (children.length === 0) return;
      children.forEach((child) => {
        console.log(this.treeMap[child.parentId]);
        if (child.parentId === this.root.id) {
          this.treeMap[child.parentId].children.splice(child.index, 1);
          this.treeMap[child.parentId].children.forEach((child, i) => {
            child.index = i;
          });
        }
      });
      let group = new Group(children, this.getUID());
      group.parentId = this.root.id;
      this.treeMap[group.id] = group;
      this.root.children.push(group);
      this.root.children.forEach((item, i) => (item.index = i));
    },
    setHandleActive(fn) {
      this.handelActive = fn;
    },
    resizeTemporaryGroup() {
      this.clearTemporaryGroup();
      this.setTemporaryGroupShow(false);
      this.setTemporaryGroupLayout({
        x: 0,
        y: 0,
        width: 0,
        height: 0,
        rotate: 0,
      });
    },
    clearTemporaryGroup() {
      this.temporaryGroup.children = [];
    },
    setTemporaryGroupShow(status) {
      this.temporaryGroup.show = status;
    },
    setTemporaryGroupLayout({ x, y, width, height, rotate = 0 }) {
      this.temporaryGroup.layout.x = x;
      this.temporaryGroup.layout.y = y;
      this.temporaryGroup.layout.width = width;
      this.temporaryGroup.layout.height = height;
      this.temporaryGroup.layout.rotate = rotate;
    },
    addTemporaryGroup(node) {
      this.temporaryGroup.children.push(node);
    },
    recordSnapshot() {
      this.snapshot.push(serializer.serialize(this.root));
      this.snapshotIndex = this.snapshot.length - 1;
    },
    redo() {
      if (this.snapshotIndex < this.snapshot.length - 1) {
        this.setActiveNode(null);
        this.snapshotIndex++;
        this.root = serializer.deserialize(this.snapshot[this.snapshotIndex]);
        const recursive = (node) => {
          this.treeMap[node.id] = node;
          if (node.children) {
            node.children.forEach((child) => {
              recursive(child);
            });
          }
        };
        this.treeMap[this.root.id] = this.root;
        this.root.children.forEach((node) => {
          recursive(node);
        });
      }
    },
    undo() {
      if (this.snapshot.length === 0) return;
      if (this.snapshotIndex > 0) {
        this.snapshotIndex--;
      }
      this.setActiveNode(null);
      this.root = serializer.deserialize(this.snapshot[this.snapshotIndex]);
      const recursive = (node) => {
        this.treeMap[node.id] = node;
        if (node.children) {
          node.children.forEach((child) => {
            recursive(child);
          });
        }
      };
      this.treeMap[this.root.id] = this.root;
      this.root.children.forEach((node) => {
        recursive(node);
      });
    },
    setContextMenu(status) {
      this.contextMenu = status;
    },
    setMoveStatus(status, mode) {
      this.moving = status;
      this.moveMode = mode;
    },
    setScale(scale) {
      this.scale = scale;
    },
    setTo(node) {
      this.to = node;
    },
    setFrom(node) {
      this.from = node;
    },
    setPullMode(mode) {
      this.pullMode = mode;
    },
    setActiveNode(node) {
      this.activeNode = node || null;
      this.activeNodeId = node ? node.id : null;
    },
    setActiveNodeId(id) {
      this.activeNodeId = id;
    },
    handleNode(event, node) {
      this.setActiveNode(node);
      this.setContextMenu(false);
      this.clearTemporaryGroup();
      this.handelActive && this.handelActive(event);
    },
    findNodeById(id) {
      return this.treeMap[id];
    },
    addNode(event) {
      const pageX = event.pageX;
      const pageY = event.pageY;
      const rect = event.target.getBoundingClientRect();
      const offsetTop = rect.top;
      const offsetLeft = rect.left;
      const x = Math.round(pageX - offsetLeft);
      const y = Math.round(pageY - offsetTop);
      const from = cloneDeep(this.from);
      from.id = this.getUID();
      from.layout = {
        ...from.layout,
        x,
        y,
      };
      this.root.children.push(from);
      from.index = this.root.children.length - 1;
      from.parentId = this.root.id;
      this.treeMap[from.id] = from;
    },
    zIndexUp(id) {
      if (id === this.root.id) return;
      if (this.treeMap[id].layout.zIndex < 100) {
        this.treeMap[id].layout.zIndex += 1;
      }
    },
    zIndexDown(id) {
      if (id === this.root.id) return;
      if (this.treeMap[id].layout.zIndex > 1) {
        this.treeMap[id].layout.zIndex -= 1;
      }
    },
    lockChange(id) {
      let lock = !this.treeMap[id].lock;
      const recursive = (node) => {
        node.lock = lock;
        if (node.children) {
          node.children.forEach((item) => {
            recursive(item);
          });
        }
      };
      recursive(this.treeMap[id]);
    },
    tearOpen(activeNode) {
      let id = activeNode.id;
      if (activeNode.type === 'temporaryGroup') {
        const ids = activeNode.children.map((item) => item.id);
        const recursive = (node) => {
          if (ids.includes(node.id)) {
            this.treeMap[node.parentId].children = this.treeMap[node.parentId].children.filter(
              (item) => item.id !== node.id,
            );
            this.treeMap[node.id].parentId = this.root.id;
            this.root.children.push(this.treeMap[node.id]);
            this.treeMap[node.id].index = this.root.children.length - 1;
          }
          if (node.children) {
            node.children.forEach((item) => {
              recursive(item);
            });
          }
        };
        this.root.children.forEach((item) => {
          recursive(item);
        });
      }
      if (activeNode.type === 'group') {
        let node = this.treeMap[id];
        let parent = this.treeMap[node.parentId];
        let ids = node.children.map((item) => item.id);
        const recursive = (node) => {
          if (ids.includes(node.id)) {
            parent.children.push(node);
            node.index = parent.children.length - 1;
            node.parentId = parent.id;
          }
          if (node.children) {
            node.children.forEach((item) => {
              recursive(item);
            });
          }
        };
        node.children.forEach((item) => {
          recursive(item);
        });
        this.treeMap[id].children = [];
        parent.children = parent.children.filter((item) => item.id !== id);
        parent.children.forEach((item, index) => {
          item.index = index;
        });
        delete this.treeMap[id];
      }
      this.setActiveNode(null);
    },
    deleteNode(node) {
      if (node.id === this.activeNode.id) {
        this.setActiveNode(null);
      }
      if (node.type === 'temporaryGroup') {
        const childIds = node.children.map((item) => item.id);
        const recursive = (node) => {
          if (node.children) {
            node.children = node.children.filter((item) => {
              recursive(item);
              return !childIds.includes(item.id);
            });
          } else return;
        };
        recursive(this.root);
      } else {
        const recursive = (node) => {
          if (node.children) {
            node.children.forEach((item) => {
              recursive(item);
            });
          }
          delete this.treeMap[node.id];
        };
        recursive(node);
        this.treeMap[node.parentId].children = this.treeMap[node.parentId].children.filter(
          (item) => item.id !== node.id,
        );
        this.treeMap[node.parentId].children.forEach((item, index) => {
          item.index = index;
        });
      }
    },
    deleteActiveNode() {
      console.log('deleteActiveNode', this.activeNode);
      if (this.activeNode) {
        this.deleteNode(this.activeNode);
      }
    },
    // 其他方法保持类似转换逻辑...
  },

  persist: {
    pick: ['root'],
    afterHydrate(ctx) {
      try {
        function recursive(node) {
          ctx.store.treeMap[node.id] = node;
          if (node.children) {
            node.children.forEach((child) => recursive(child));
          }
        }
        recursive(ctx.store.root);
      } catch (error) {
        console.log('afterHydrate', error);
      }
    },
    debug: true,
    serializer: serializer,
  },
});

export default useNodeTreeStore;
